﻿#region "USING"
using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using System.Diagnostics;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using System.Threading;



#endregion
public delegate void AddRezDelegate(Rezult rez);
public class Worker
{
    #region Переменные
    public int k;
    public List<Task> tasks = new List<Task>();
    public event AddRezDelegate AddRez;
    public IPAddress IP { get; set; }
    public Task task = null; //Текущая задача
    volatile bool aborted;   // Ключевое слово volatile гарантирует, что abort не будет кешироваться потоком
    public string kapcha_key { get; set; }
    public string kapcha_value { get; set; }
    Thread thread { get; set; }
    Client client;
    public EventWaitHandle waiter = new AutoResetEvent(false);
    CookieContainer cookie;
    Random r = new Random();
    int port { get { return r.Next(5000, 6000); } }
    string kapcha_url { get; set; }
    int Max_position = 500;
    WebBrowser browser;

    #endregion
    #region REGET
    Regex reg_capcha = new Regex(@"(?<img><img src=\u0022/sorry/.*?\u0022>).*?(?<form><form.*?</form>)", RegexOptions.None);
    Regex reg_loc = new Regex(@"Location: (?<loc>.*)", RegexOptions.None);
    Regex reg_head = new Regex(@".*?\r\n\r", RegexOptions.Singleline);
    Regex reg_cookie = new Regex(@"Set-Cookie: (?<1>yandexuid=(\d)*);", RegexOptions.IgnoreCase);
    Regex reg_status = new Regex(@"HTTP/[^ ]* (?<status>[\w]*)", RegexOptions.IgnoreCase);
    Regex reg_script = new Regex(@"<script.*?>.*?</script>", RegexOptions.IgnoreCase | RegexOptions.Singleline);
    Regex reg_b = new Regex(@"<b>.*?</b>", RegexOptions.IgnoreCase | RegexOptions.Singleline);
    Regex reg_url = new Regex(@"[-A-z0-9_.]*", RegexOptions.IgnoreCase);
    Regex reg_capchaimage = new Regex(@"http://captcha\.yandex\.net/image\?key=(?<key>[^\u0022]*)\u0022>", RegexOptions.IgnoreCase);
    Regex r_capcha = new Regex(@"<img src=\u0022http://captcha.yandex.net/image\?key=(?<key>.*?)\u0022>", RegexOptions.IgnoreCase);
    Regex reg_encoding = new Regex(@"charset=(?<CodePage>[^
]*)", RegexOptions.IgnoreCase);
    #endregion
    public Worker(Client _client,WebBrowser _browser, AddRezDelegate addrez_void )
    {
        browser = _browser;
        browser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(browser_DocumentCompleted);
        this.client = _client;
        AddRez += addrez_void;
        this.thread = new Thread(Work);
        this.thread.Start();
    }
    public void Abort()
    {
        aborted = true;
    }
   
    IPEndPoint Bind(ServicePoint servicePoint, IPEndPoint  remoteEndPoint, int retryCount) 
    {
        return new IPEndPoint(this.IP, this.port);
    }
   
    void GetPage(Uri url)
    {
        browser.Navigate(url);
    }
    int wait;
    string pos = "?", tmp = "";
    int i = 0, curr = 0;
   
    void browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
    {
        if (task == null)
            return;
        if (e.Url.AbsolutePath.Contains("sorry") || e.Url.AbsolutePath.Contains("showcaptcha"))
            return;
        if (!e.Url.AbsolutePath.Contains("search") && !e.Url.AbsolutePath.Contains("yandsearch"))
            return;

        Rezult rezult = new Rezult();
        rezult.poisk = task.poisk.id;
        rezult.home = task.home;
        rezult.dt = DateTime.Now.ToShortDateString();
        rezult.slovo = task.slovo;

        WebBrowser browser = (WebBrowser)sender;
        string rez = browser.DocumentText;
        MatchCollection mt = task.poisk.reg.Matches(rez);
        bool found = false;
        foreach (Match m in mt)
        {
            i++;
            tmp = m.Groups["home"].Value.ToLower();
            if (tmp.Contains(task.home))
            {
                pos = m.Groups["pos"].Value;
                rezult.pos = pos;
                AddRez(rezult);
                client.ToLog(new Log(LogType.событие, task.ToString() + "=" + pos), false);
                wait = task.poisk.wait;
                found = true;
                task = null;
                Thread.Sleep(wait /k);
                break;
            }
        }
        if (!found) //ненашел выше
        {

            curr = (short)(task.poisk.PageSize * (task.page + 1));
            client.ToLog(new Log(LogType.событие, task.ToString() + "=позиция>" + curr), false);

            if (Max_position > (task.page + 1) * task.poisk.PageSize)
            {
                pos = ">" + (task.page + 1) * task.poisk.PageSize;
                task.page++;
                tasks.Add(task);
                client.CheckTask(task, true);
            }
            else
            {
                client.ToLog(new Log(LogType.событие, task.ToString() + "не найдена до " + Max_position + " позиции"), false);
                pos = ">" + Max_position;
            }
            rezult.pos = pos;
            AddRez(rezult);
            waiter.Set();
            task = null;
        }
    }

   
    public void Work()
    {            
        if (task == null && tasks.Count > 0)
        {
            task = tasks[0];
            tasks.Remove(task);
            client.CheckTask(task, false);
            GetPage(task.url);
        }
    }

    public override string ToString()
    {
        return this.IP.ToString();
    }
}